with GNAT.String_Split;
with Ada.Strings.Bounded;

generic

   -- allow varied types to limit bytes in download, conversion
   --    into String for return rather than using a function parameter

   Max_Download : Positive;

--
-- Website_Retrieval
--
-- public
--
--    Retrieve: Download a URL using HTTP.
--
-- private
--
--    Parse_Host_Address: Separate URL into protocol, host and any path or
--       query string.
--

package Website_Retrieval is

   --
   -- constants
   --

   HOST_MAX_LENGTH         : constant := 250;

   HOST_MIN_LENGTH         : constant := 8;

   PROTOCOL_MAX_LENGTH     : constant := 8;

   HTTP_REQUEST_MAX_LENGTH : constant := 900;

   FILE_NAME_MAX_LENGTH    : constant := 100;

   --
   -- bound strings
   --

   package Limit_Str renames Ada.Strings.Bounded;

   package Host_Address_Type is new Limit_Str.Generic_Bounded_Length(

         HOST_MAX_LENGTH );

   subtype Host_Address_Sub_Type is Host_Address_Type.Bounded_String;

   -- contains String of website contents
   -- use generic rather than a parameter to control download size

   package Output_String_Type is new Limit_Str.Generic_Bounded_Length(

         Max_Download);

   Output_Str : Output_String_Type.Bounded_String;

   -- file output

   package File_Name_Type is new Limit_Str.Generic_Bounded_Length(

         FILE_NAME_MAX_LENGTH );

   subtype File_Name_Sub_Type is File_Name_Type.Bounded_String;

   -- empty file name place holder, if unpopulated should suffice as a null
   --    object

   subtype Empty_File_Name_Type is File_Name_Type.Bounded_String;

   Empty_File_Name : Empty_File_Name_Type;

   --
   -- enumerations
   --

   type Write_To is( String_Variable, File );

   --
   -- exceptions
   --

   Protocol_Invalid_Length     : exception;
   Host_Address_Invalid_Length : exception;
   Host_Unsupported_Protocol   : exception;  -- example: require http or https
   File_Name_Invalid           : exception;

   Download_Empty              : exception;

   --
   -- interface
   --

   type Website_Retrieval_Object is interface;

   --
   -- Retrieve
   --
   --    Download a URL using HTTP.
   --
   --    Accepts canonical URL or IP and any path or query string.
   --

   procedure Retrieve( Website_Retrieval_Obj : in out Website_Retrieval_Object;

                       Host_Address   : in Host_Address_Sub_Type;

                       Output         : in Write_To := Write_To'Value(
                           "String_Variable");

                       File_Name_Arg  : in File_Name_Type.Bounded_String :=
                           Empty_File_Name;

                       Output_Str_Arg : in out Output_String_Type
                           .Bounded_String;

                       Verbose        : in Boolean := false )

         is abstract;


private

   --
   -- enumerations
   --

   type Address_Portion is( Protocol, Host, Path );

   --
   -- exceptions
   --

   Protocol_Parse_Failure  : exception;
   Host_Parse_Failure      : exception;
   Path_Parse_Failure      : exception;

   Invalid_Address_Portion : exception;

   --
   -- functions
   --


   --
   -- Parse_Host
   --
   --    Separate URL into protocol, host and any path or query string.
   --

   function Parse_Host( Host_Address : in Host_Address_Sub_Type;

                        Address_Portion_Enum : Address_Portion :=
                           Address_Portion'Value("Host"))

         return String;


   --
   -- Get_Protocol
   --
   --    Find protocol used, 'http://' or 'https://'.
   --

   function Get_Protocol( Host_Pieces : in GNAT.String_Split.Slice_Set )

         return String;


   --
   -- Get_Host
   --
   --    Find domain, 'www.myhost.com'.
   --

   function Get_Host( Host_Pieces : in GNAT.String_Split.Slice_Set )

         return String;


   --
   -- Get_Path
   --
   --    Find any path or query string.
   --
   --    Returns empty String if none found.
   --

   function Get_Path( Host_Pieces : in GNAT.String_Split.Slice_Set )

         return String;


end Website_Retrieval;